"""
AI服务管理模块
负责服务状态监控、性能统计、健康检查和配置管理
"""
import asyncio
import time
from typing import Dict, Any, List, Optional, Union
from datetime import datetime, timedelta
from dataclasses import dataclass, asdict
from enum import Enum
import json
import threading
from concurrent.futures import ThreadPoolExecutor
import logging

from services.ai_service_factory import (
    ai_service_factory, AIService, ServiceConfig, 
    ServiceRequest, ServiceResponse, ServiceType, ServiceStatus
)
from services.ai_analysis_services import register_ai_services
from core.config import settings
from core.logging_config import get_logger
from core.exceptions import AIServiceError, ValidationError

logger = get_logger("ai_service_manager")


class ServiceHealthStatus(str, Enum):
    """服务健康状态"""
    HEALTHY = "healthy"
    DEGRADED = "degraded"
    UNHEALTHY = "unhealthy"
    UNKNOWN = "unknown"


class AlertLevel(str, Enum):
    """告警级别"""
    INFO = "info"
    WARNING = "warning"
    ERROR = "error"
    CRITICAL = "critical"


@dataclass
class ServiceAlert:
    """服务告警"""
    id: str
    service_name: str
    alert_type: str
    level: AlertLevel
    message: str
    timestamp: datetime
    resolved: bool = False
    resolved_at: Optional[datetime] = None
    metadata: Dict[str, Any] = None
    
    def __post_init__(self):
        if self.metadata is None:
            self.metadata = {}


@dataclass
class ServiceUsageStats:
    """服务使用统计"""
    service_name: str
    date: datetime
    request_count: int = 0
    success_count: int = 0
    error_count: int = 0
    average_response_time: float = 0.0
    total_processing_time: float = 0.0
    peak_concurrent_requests: int = 0
    
    def add_request(self, success: bool, response_time: float):
        """添加请求统计"""
        self.request_count += 1
        self.total_processing_time += response_time
        
        if success:
            self.success_count += 1
        else:
            self.error_count += 1
        
        # 更新平均响应时间
        if self.request_count > 0:
            self.average_response_time = self.total_processing_time / self.request_count


class AIServiceManager:
    """AI服务管理器"""
    
    def __init__(self):
        self.services: Dict[str, AIService] = {}
        self.alerts: List[ServiceAlert] = []
        self.usage_stats: Dict[str, List[ServiceUsageStats]] = {}
        self.config_history: List[Dict[str, Any]] = []
        self._executor = ThreadPoolExecutor(max_workers=5)
        self._monitoring_task = None
        self._health_check_task = None
        self._cleanup_task = None
        self._running = False
        self._lock = threading.Lock()
        
        # 监控配置
        self.health_check_interval = 60  # 健康检查间隔（秒）
        self.metrics_collection_interval = 30  # 指标收集间隔（秒）
        self.alert_retention_days = 7  # 告警保留天数
        self.stats_retention_days = 30  # 统计保留天数
        
        # 告警阈值
        self.error_rate_threshold = 0.1  # 错误率阈值
        self.response_time_threshold = 30.0  # 响应时间阈值（秒）
        self.concurrency_threshold = 0.8  # 并发阈值
        
    async def initialize(self) -> bool:
        """初始化服务管理器"""
        try:
            logger.info("初始化AI服务管理器...")
            
            # 注册AI服务
            register_ai_services()
            
            # 创建默认服务实例
            await self._create_default_services()
            
            # 启动服务
            await self.start_all_services()
            
            # 启动监控任务
            self._start_monitoring()
            
            logger.info("AI服务管理器初始化成功")
            return True
            
        except Exception as e:
            logger.error(f"AI服务管理器初始化失败: {str(e)}")
            return False
    
    async def _create_default_services(self):
        """创建默认服务实例"""
        from services.ai_analysis_services import get_default_service_config
        
        service_types = [
            ServiceType.INFORMATION_EXTRACTION,
            ServiceType.POLLUTION_TYPE_RECOGNITION,
        ]
        
        for service_type in service_types:
            try:
                config = get_default_service_config(service_type)
                service = ai_service_factory.create_service(config)
                self.services[config.name] = service
                
                # 初始化使用统计
                self.usage_stats[config.name] = []
                
                logger.info(f"创建默认服务: {config.name}")
                
            except Exception as e:
                logger.error(f"创建默认服务失败 {service_type}: {str(e)}")
    
    async def start_all_services(self) -> Dict[str, bool]:
        """启动所有服务"""
        logger.info("启动所有AI服务...")
        
        results = await ai_service_factory.start_all_services()
        
        # 记录启动结果
        for service_name, success in results.items():
            if success:
                logger.info(f"服务启动成功: {service_name}")
            else:
                self._create_alert(
                    service_name,
                    "service_start_failed",
                    AlertLevel.ERROR,
                    f"服务启动失败: {service_name}"
                )
        
        return results
    
    async def stop_all_services(self):
        """停止所有服务"""
        logger.info("停止所有AI服务...")
        
        # 停止监控任务
        self._stop_monitoring()
        
        # 停止服务
        await ai_service_factory.stop_all_services()
        
        logger.info("所有AI服务已停止")
    
    def _start_monitoring(self):
        """启动监控任务"""
        if self._running:
            return
        
        self._running = True
        
        # 启动健康检查任务
        self._health_check_task = asyncio.create_task(self._health_check_loop())
        
        # 启动指标收集任务
        self._monitoring_task = asyncio.create_task(self._metrics_collection_loop())
        
        # 启动清理任务
        self._cleanup_task = asyncio.create_task(self._cleanup_loop())
        
        logger.info("AI服务监控任务已启动")
    
    def _stop_monitoring(self):
        """停止监控任务"""
        self._running = False
        
        if self._health_check_task:
            self._health_check_task.cancel()
        
        if self._monitoring_task:
            self._monitoring_task.cancel()
        
        if self._cleanup_task:
            self._cleanup_task.cancel()
        
        logger.info("AI服务监控任务已停止")
    
    async def _health_check_loop(self):
        """健康检查循环"""
        while self._running:
            try:
                await self._perform_health_checks()
                await asyncio.sleep(self.health_check_interval)
            except asyncio.CancelledError:
                break
            except Exception as e:
                logger.error(f"健康检查异常: {str(e)}")
                await asyncio.sleep(self.health_check_interval)
    
    async def _metrics_collection_loop(self):
        """指标收集循环"""
        while self._running:
            try:
                self._collect_metrics()
                await asyncio.sleep(self.metrics_collection_interval)
            except asyncio.CancelledError:
                break
            except Exception as e:
                logger.error(f"指标收集异常: {str(e)}")
                await asyncio.sleep(self.metrics_collection_interval)
    
    async def _cleanup_loop(self):
        """清理循环"""
        while self._running:
            try:
                self._cleanup_old_data()
                await asyncio.sleep(3600)  # 每小时清理一次
            except asyncio.CancelledError:
                break
            except Exception as e:
                logger.error(f"数据清理异常: {str(e)}")
                await asyncio.sleep(3600)
    
    async def _perform_health_checks(self):
        """执行健康检查"""
        try:
            health_results = await ai_service_factory.health_check_all()
            
            for service_name, result in health_results["details"].items():
                is_healthy = result.get("healthy", False)
                
                if not is_healthy:
                    # 检查是否已有未解决的告警
                    existing_alert = self._get_unresolved_alert(service_name, "health_check_failed")
                    
                    if not existing_alert:
                        self._create_alert(
                            service_name,
                            "health_check_failed",
                            AlertLevel.WARNING,
                            f"服务健康检查失败: {result.get('error', 'Unknown error')}"
                        )
                else:
                    # 解决相关告警
                    self._resolve_alerts(service_name, "health_check_failed")
            
        except Exception as e:
            logger.error(f"健康检查执行失败: {str(e)}")
    
    def _collect_metrics(self):
        """收集指标"""
        try:
            current_date = datetime.now().date()
            
            for service_name, service in self.services.items():
                # 获取服务指标
                service_status = service.get_status()
                metrics = service_status.get("metrics", {})
                
                # 更新今日统计
                today_key = current_date.isoformat()
                
                if today_key not in self.usage_stats[service_name]:
                    self.usage_stats[service_name].append(
                        ServiceUsageStats(service_name=service_name, date=current_date)
                    )
                
                today_stats = self.usage_stats[service_name][-1]
                
                # 检查是否需要更新指标
                if metrics.get("request_count", 0) > today_stats.request_count:
                    # 计算新增的请求
                    new_requests = metrics["request_count"] - today_stats.request_count
                    new_successes = metrics["success_count"] - today_stats.success_count
                    new_errors = metrics["error_count"] - today_stats.error_count
                    
                    # 更新统计
                    today_stats.request_count = metrics["request_count"]
                    today_stats.success_count = metrics["success_count"]
                    today_stats.error_count = metrics["error_count"]
                    
                    # 更新并发峰值
                    current_concurrency = metrics.get("current_queue_size", 0)
                    today_stats.peak_concurrent_requests = max(
                        today_stats.peak_concurrent_requests,
                        current_concurrency
                    )
                    
                    # 检查告警条件
                    self._check_alert_conditions(service_name, today_stats)
        
        except Exception as e:
            logger.error(f"指标收集失败: {str(e)}")
    
    def _check_alert_conditions(self, service_name: str, stats: ServiceUsageStats):
        """检查告警条件"""
        if stats.request_count == 0:
            return
        
        # 检查错误率
        error_rate = stats.error_count / stats.request_count
        if error_rate > self.error_rate_threshold:
            self._create_alert(
                service_name,
                "high_error_rate",
                AlertLevel.WARNING,
                f"错误率过高: {error_rate:.2%} (阈值: {self.error_rate_threshold:.2%})",
                {"error_rate": error_rate, "threshold": self.error_rate_threshold}
            )
        
        # 检查响应时间
        if stats.average_response_time > self.response_time_threshold:
            self._create_alert(
                service_name,
                "slow_response",
                AlertLevel.WARNING,
                f"响应时间过长: {stats.average_response_time:.2f}s (阈值: {self.response_time_threshold}s)",
                {"avg_response_time": stats.average_response_time, "threshold": self.response_time_threshold}
            )
    
    def _create_alert(self, service_name: str, alert_type: str, level: AlertLevel, message: str, metadata: Dict[str, Any] = None):
        """创建告警"""
        import uuid
        
        alert = ServiceAlert(
            id=str(uuid.uuid4()),
            service_name=service_name,
            alert_type=alert_type,
            level=level,
            message=message,
            timestamp=datetime.now(),
            metadata=metadata or {}
        )
        
        with self._lock:
            self.alerts.append(alert)
        
        logger.warning(f"服务告警 [{level.value}] {service_name}: {message}")
    
    def _get_unresolved_alert(self, service_name: str, alert_type: str) -> Optional[ServiceAlert]:
        """获取未解决的告警"""
        with self._lock:
            for alert in self.alerts:
                if (alert.service_name == service_name and 
                    alert.alert_type == alert_type and 
                    not alert.resolved):
                    return alert
        return None
    
    def _resolve_alerts(self, service_name: str, alert_type: str):
        """解决告警"""
        with self._lock:
            for alert in self.alerts:
                if (alert.service_name == service_name and 
                    alert.alert_type == alert_type and 
                    not alert.resolved):
                    alert.resolved = True
                    alert.resolved_at = datetime.now()
                    logger.info(f"告警已解决: {service_name} - {alert_type}")
    
    def _cleanup_old_data(self):
        """清理旧数据"""
        try:
            cutoff_date = datetime.now() - timedelta(days=self.alert_retention_days)
            
            # 清理旧告警
            with self._lock:
                self.alerts = [
                    alert for alert in self.alerts
                    if alert.timestamp > cutoff_date
                ]
            
            # 清理旧统计
            stats_cutoff_date = datetime.now() - timedelta(days=self.stats_retention_days)
            for service_name in self.usage_stats:
                self.usage_stats[service_name] = [
                    stats for stats in self.usage_stats[service_name]
                    if stats.date > stats_cutoff_date.date()
                ]
            
            logger.info("清理旧数据完成")
            
        except Exception as e:
            logger.error(f"清理旧数据失败: {str(e)}")
    
    async def process_request(self, service_type: ServiceType, data: Dict[str, Any], 
                          parameters: Dict[str, Any] = None) -> ServiceResponse:
        """处理AI服务请求"""
        try:
            # 创建请求
            from services.ai_service_factory import create_service_request
            request = create_service_request(service_type, data, parameters)
            
            # 处理请求
            response = await ai_service_factory.process_request(request)
            
            # 记录处理结果
            if response.success:
                logger.info(f"服务请求处理成功: {service_type.value}")
            else:
                logger.error(f"服务请求处理失败: {service_type.value}, 错误: {response.error_message}")
            
            return response
            
        except Exception as e:
            logger.error(f"处理AI服务请求异常: {str(e)}")
            return ServiceResponse(
                request_id="",
                service_type=service_type,
                success=False,
                error_message=str(e)
            )
    
    def get_service_status(self) -> Dict[str, Any]:
        """获取服务状态"""
        return ai_service_factory.get_service_status()
    
    def get_service_health(self) -> Dict[str, Any]:
        """获取服务健康状态"""
        return {
            "total_services": len(self.services),
            "healthy_services": sum(1 for s in self.services.values() if s.status == ServiceStatus.READY),
            "unhealthy_services": sum(1 for s in self.services.values() if s.status == ServiceStatus.ERROR),
            "alerts": {
                "total": len(self.alerts),
                "unresolved": len([a for a in self.alerts if not a.resolved]),
                "by_level": self._count_alerts_by_level()
            },
            "last_health_check": datetime.now().isoformat()
        }
    
    def _count_alerts_by_level(self) -> Dict[str, int]:
        """按级别统计告警"""
        counts = {level.value: 0 for level in AlertLevel}
        
        with self._lock:
            for alert in self.alerts:
                if not alert.resolved:
                    counts[alert.level.value] += 1
        
        return counts
    
    def get_service_metrics(self, service_name: Optional[str] = None, 
                          days: int = 7) -> Dict[str, Any]:
        """获取服务指标"""
        try:
            cutoff_date = datetime.now() - timedelta(days=days)
            
            if service_name:
                if service_name not in self.usage_stats:
                    return {"error": f"服务不存在: {service_name}"}
                
                stats = self.usage_stats[service_name]
                filtered_stats = [s for s in stats if s.date >= cutoff_date.date()]
                
                return {
                    "service_name": service_name,
                    "period_days": days,
                    "statistics": [asdict(s) for s in filtered_stats]
                }
            else:
                # 返回所有服务的指标
                result = {"period_days": days, "services": {}}
                
                for name, stats_list in self.usage_stats.items():
                    filtered_stats = [s for s in stats_list if s.date >= cutoff_date.date()]
                    result["services"][name] = [asdict(s) for s in filtered_stats]
                
                return result
                
        except Exception as e:
            logger.error(f"获取服务指标失败: {str(e)}")
            return {"error": str(e)}
    
    def get_alerts(self, service_name: Optional[str] = None, 
                  level: Optional[AlertLevel] = None, 
                  resolved: Optional[bool] = None) -> List[Dict[str, Any]]:
        """获取告警列表"""
        try:
            with self._lock:
                filtered_alerts = self.alerts
            
            # 应用过滤条件
            if service_name:
                filtered_alerts = [a for a in filtered_alerts if a.service_name == service_name]
            
            if level:
                filtered_alerts = [a for a in filtered_alerts if a.level == level]
            
            if resolved is not None:
                filtered_alerts = [a for a in filtered_alerts if a.resolved == resolved]
            
            # 按时间倒序排列
            filtered_alerts.sort(key=lambda a: a.timestamp, reverse=True)
            
            return [asdict(alert) for alert in filtered_alerts[:100]]  # 最多返回100条
            
        except Exception as e:
            logger.error(f"获取告警列表失败: {str(e)}")
            return []
    
    def get_service_capabilities(self) -> Dict[str, Any]:
        """获取服务能力"""
        return ai_service_factory.get_service_capabilities()
    
    async def update_service_config(self, service_name: str, config_updates: Dict[str, Any]) -> bool:
        """更新服务配置"""
        try:
            service = self.services.get(service_name)
            if not service:
                raise ValidationError(f"服务不存在: {service_name}")
            
            # 记录配置变更历史
            self.config_history.append({
                "timestamp": datetime.now().isoformat(),
                "service_name": service_name,
                "changes": config_updates
            })
            
            # 更新配置
            for key, value in config_updates.items():
                if hasattr(service.config, key):
                    setattr(service.config, key, value)
            
            logger.info(f"服务配置更新成功: {service_name}")
            return True
            
        except Exception as e:
            logger.error(f"服务配置更新失败: {str(e)}")
            return False
    
    async def restart_service(self, service_name: str) -> bool:
        """重启服务"""
        try:
            service = self.services.get(service_name)
            if not service:
                raise ValidationError(f"服务不存在: {service_name}")
            
            logger.info(f"重启服务: {service_name}")
            
            # 停止服务
            await service.stop()
            
            # 等待一段时间
            await asyncio.sleep(2)
            
            # 启动服务
            success = await service.start()
            
            if success:
                logger.info(f"服务重启成功: {service_name}")
            else:
                self._create_alert(
                    service_name,
                    "service_restart_failed",
                    AlertLevel.ERROR,
                    f"服务重启失败: {service_name}"
                )
            
            return success
            
        except Exception as e:
            logger.error(f"服务重启失败: {str(e)}")
            return False


# 全局AI服务管理器
ai_service_manager = AIServiceManager()